package nettyTest.netty3Test;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;

public class EchoServer {

	static final boolean SSL = System.getProperty("ssl") != null;
	static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));

	public static void main(String[] args) throws Exception {
		final SslContext sslCtx;
		if (SSL) {
			SelfSignedCertificate ssc = new SelfSignedCertificate();
			sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
		} else {
			sslCtx = null;
		}

		EventLoopGroup bossGroup = new NioEventLoopGroup(1);
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			// 给bootStrap设定bossGroup 和 work的事件循环组
			b.group(bossGroup, workerGroup)
					// 给bootStrap设定ChannelFactory
					.channel(NioServerSocketChannel.class)
					// 添加一些参数
					.option(ChannelOption.SO_BACKLOG, 100)
					// 给bootStrap设定LoggingHandler属于boss的
//					.handler(new LoggingHandler(LogLevel.INFO))
					// 给bootStrap设定 handler 属于child的
					.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ChannelPipeline p = ch.pipeline();
					if (sslCtx != null) {
//						添加 一个 SslHandler
						p.addLast(sslCtx.newHandler(ch.alloc()));
					}
					p.addLast(new LoggingHandler(LogLevel.INFO));
					p.addLast(new EchoServerHandler());
				}
			});

			// Start the server.
			ChannelFuture f = b
					// 绑定端口
					.bind(PORT)
					// 阻塞
					.sync();

			// Wait until the server socket is closed.
			f.channel().closeFuture().sync();
		} finally {
			// Shut down all event loops to terminate all threads.
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

}
